from mastodon import Mastodon
from mastodon import Mastodon as M

import re
import defusedxml
from defusedxml.ElementTree import fromstring

from mykochi import mykochi
import nltk

def connect_mastodon():
    mastodon = Mastodon(
        access_token = 'token.secret',
        api_base_url = 'https://botsin.space/'
    )
    return mastodon

class Bot:
    def __init__(self, name, mastodon):
        self.m = mastodon
        self.name = name
        self.myid = self.m.me().id

class SubBot:
    pass

class EchoSubBot(SubBot):
    def react(self, message, status=None, rootid=None):
        return message

class GameSubBot(SubBot):
    def react(self, message, status=None, rootid=None):
        return (b"conversation root id: %d" % rootid)

from nltk.corpus import stopwords
stoplist = stopwords.words('german')

import logging

class MyKochiSubBot(SubBot):
    def __init__(self):
        self.mykochi = mykochi.MyKochi()
    def react(self, message, status=None, rootid=None):
        print(type(message))
        if type(message) is bytes:
            message = message.decode(errors="ignore")
        message = re.sub("@\w+", "", message)
        message = re.sub("#", "", message)
        input_tokens = nltk.tokenize.word_tokenize(message)
        tokens = [tok.lower() for tok in input_tokens if tok not in stoplist] 
        tokens = sorted(tokens, key=len, reverse=True)
        print("going to use %s (%s)" % (tokens[0], tokens[0:10]))
        return self.mykochi.sentence(tokens[0]).encode("utf-8")[0:256]

def get_roottoot(m, tootid):
    ancestors = m.status_context(id=tootid).get('ancestors')
    if len(ancestors) == 0:
        return tootid
    else:
        return get_roottoot(m, ancestors[0].get('id'))

import xml

class MetaBot(Bot):
    subs = {}
    def addsub(self, name, subbot):
        self.subs[name] = subbot

    def interact(self):

        # fetch new notifications (new = not yet dismissed)
        notifs = self.m.notifications()

        print("fetched %d notifs" % len(notifs))

        for i in range(len(notifs)):
            notif = notifs[i]

            print("type", notif.get("type"))
            if notif.get("type") != "mention":
                continue

            stat = notif.get("status")
            if stat is None:
                continue
            # if stat.get("visibility") == "direct":
            #     print("ignoring direct message")
            #     continue
            ment = stat.get("mentions")
            print(ment)
            cont = stat.get("content")
            # print(cont)

            if len(list(filter(lambda x: x.get("id") != self.myid, ment))) > 0:
                print("someone else is mentioned")
                continue
            if cont is None:
                continue
            else:

                rootid = get_roottoot(self.m, stat.get("id"))

                roottoot = m.status(id=rootid)
                rootcont = roottoot.get("content") if roottoot is not None else None

                try:
                    fs = fromstring(cont)
                    bt = defusedxml.ElementTree.tostring(fs, encoding="utf8", method="text")
                    mat = re.search(b"\[(.*?)\] *(.*)", bt)
                # except xml.parsers.expat.ExpatError as e:
                # except xml.etree.ElementTree.ParseError as e:
                except Exception as e:
                    # print(e)
                    mat = None
                if mat is None:
                    print("no match of pattern, trying root toot content")
                    if rootcont is not None:
                        try:
                            fs_of_root = fromstring(rootcont)
                            bt_of_root = defusedxml.ElementTree.tostring(fs_of_root, encoding="utf8", method="text")
                            mat_in_root = re.search(b"\[(.*?)\] *(.*)", bt_of_root)
                        except Exception as e:
                            print(e)
                            mat_in_root = None
                        if mat_in_root is None:
                            print("no match there either")
                            continue

                        botname = mat_in_root.group(1).decode(errors="ignore")
                        botmess = bt
                else:
                    botname = mat.group(1).decode(errors="ignore")
                    botmess = mat.group(2).decode(errors="ignore")
                
                subbot = self.subs.get(botname)
                if subbot is None:
                    print("no such subbot registered, %s" % botname)
                    continue

                reaction = subbot.react(botmess, status=stat, rootid=rootid)
                print("would react with \"%s\"" % reaction)

                self.m.status_reply(to_status=stat, status=reaction.decode(errors="ignore"))
                self.m.notifications_dismiss(notif.get("id"))


if __name__=="__main__":
    m = connect_mastodon()
    mb = MetaBot("meta", m)
    mb.addsub("echo", EchoSubBot())
    mb.addsub("game", GameSubBot())
    mb.addsub("pseudokochi", MyKochiSubBot())
    mb.interact()

